//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//
/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using EffiProz.Core.DataTypes;
using EffiProz.Core.Lib;


namespace EffiProz.Core.DbInfos
{

    // fredt@users - 1.7.2 - structural modifications to allow inheritance
    // boucherB@users 20020305 - completed inheritance work, including const access
    // boucherB@users 20020305 - javadoc updates/corrections
    // boucherB@users 20020305 - SYSTEM_VIEWS brought _in line with SQL 200n
    // boucherb@users 20050514 - further SQL 200n metdata support

    /**
     * Base class for system tables. Includes a factory method which returns the
     * most complete implementation available _in the jar. This base implementation
     * knows the names of all system tables but returns null for any system table.
     * <p>
     * This class has been developed from scratch to replace the previous
     * DatabaseInformation implementations. <p>
     *
     * @author boucherb@users
     * @version 1.8.0
     * @since 1.7.2
     */
    public class DatabaseInformation
    {
   // ids for system table names strictly in order of sysTableNames[]
    protected const int ID_SYSTEM_BESTROWIDENTIFIER = 0;
    protected const int ID_SYSTEM_COLUMNS           = 1;
    protected const int ID_SYSTEM_CROSSREFERENCE    = 2;
    protected const int ID_SYSTEM_INDEXINFO         = 3;
    protected const int ID_SYSTEM_PRIMARYKEYS       = 4;
    protected const int ID_SYSTEM_PROCEDURECOLUMNS  = 5;
    protected const int ID_SYSTEM_PROCEDURES        = 6;
    protected const int ID_SYSTEM_SCHEMAS           = 7;
    protected const int ID_SYSTEM_TABLES            = 8;
    protected const int ID_SYSTEM_TABLETYPES        = 9;
    protected const int ID_SYSTEM_TYPEINFO          = 10;
    protected const int ID_SYSTEM_UDTS              = 11;
    protected const int ID_SYSTEM_USERS             = 12;    //-- ref in SqlFile only
    protected const int ID_SYSTEM_VERSIONCOLUMNS    = 13;    //-- returns autogenerated columns
    protected const int ID_SYSTEM_SEQUENCES = 14;            //-- same as SEQUENCES

    // HSQLDB-specific
    protected const int ID_SYSTEM_CACHEINFO             = 15;
    protected const int ID_SYSTEM_CONNECTION_PROPERTIES = 16;
    protected const int ID_SYSTEM_PROPERTIES            = 17;
    protected const int ID_SYSTEM_SESSIONINFO           = 18;
    protected const int ID_SYSTEM_SESSIONS              = 19;
    protected const int ID_SYSTEM_TEXTTABLES            = 20;

    // SQL 200n tables
    protected const int ID_ADMINISTRABLE_ROLE_AUTHORIZATIONS = 21;
    protected const int ID_APPLICABLE_ROLES                  = 22;
    protected const int ID_ASSERTIONS                        = 23;
    protected const int ID_AUTHORIZATIONS                    = 24;
    protected const int ID_CHARACTER_SETS                    = 25;
    protected const int ID_CHECK_CONSTRAINT_ROUTINE_USAGE    = 26;
    protected const int ID_CHECK_CONSTRAINTS                 = 27;
    protected const int ID_COLLATIONS                        = 28;
    protected const int ID_COLUMN_COLUMN_USAGE               = 29;
    protected const int ID_COLUMN_DOMAIN_USAGE               = 30;
    protected const int ID_COLUMN_PRIVILEGES                 = 31;
    protected const int ID_COLUMN_UDT_USAGE                  = 32;
    protected const int ID_COLUMNS                           = 33;
    protected const int ID_CONSTRAINT_COLUMN_USAGE           = 34;
    protected const int ID_CONSTRAINT_TABLE_USAGE            = 35;
    protected const int ID_DATA_TYPE_PRIVILEGES              = 36;
    protected const int ID_DOMAIN_CONSTRAINTS                = 37;
    protected const int ID_DOMAINS                           = 38;
    protected const int ID_ENABLED_ROLES                     = 39;
    protected const int ID_INFORMATION_SCHEMA_CATALOG_NAME   = 40;
    protected const int ID_ASSEMBLY_ASSEMBLY_USAGE           = 41;
    protected const int ID_ASSEMBLIES                        = 42;
    protected const int ID_KEY_COLUMN_USAGE                  = 43;
    protected const int ID_METHOD_SPECIFICATIONS             = 44;
    protected const int ID_MODULE_COLUMN_USAGE               = 45;
    protected const int ID_MODULE_PRIVILEGES                 = 46;
    protected const int ID_MODULE_TABLE_USAGE                = 47;
    protected const int ID_MODULES                           = 48;
    protected const int ID_PARAMETERS                        = 49;
    protected const int ID_REFERENTIAL_CONSTRAINTS           = 50;
    protected const int ID_ROLE_AUTHORIZATION_DESCRIPTORS    = 51;
    protected const int ID_ROLE_COLUMN_GRANTS                = 52;
    protected const int ID_ROLE_MODULE_GRANTS                = 53;
    protected const int ID_ROLE_ROUTINE_GRANTS               = 54;
    protected const int ID_ROLE_TABLE_GRANTS                 = 55;
    protected const int ID_ROLE_UDT_GRANTS                   = 56;
    protected const int ID_ROLE_USAGE_GRANTS                 = 57;
    protected const int ID_ROUTINE_COLUMN_USAGE              = 58;
    protected const int ID_ROUTINE_ASSEMBLY_USAGE            = 59;
    protected const int ID_ROUTINE_PRIVILEGES                = 60;
    protected const int ID_ROUTINE_ROUTINE_USAGE             = 61;
    protected const int ID_ROUTINE_SEQUENCE_USAGE            = 62;
    protected const int ID_ROUTINE_TABLE_USAGE               = 63;
    protected const int ID_ROUTINES                          = 64;
    protected const int ID_SCHEMATA                          = 65;
    protected const int ID_SEQUENCES                         = 66;
    protected const int ID_SQL_FEATURES                      = 67;
    protected const int ID_SQL_IMPLEMENTATION_INFO           = 68;
    protected const int ID_SQL_PACKAGES                      = 69;
    protected const int ID_SQL_PARTS                         = 70;
    protected const int ID_SQL_SIZING                        = 71;
    protected const int ID_SQL_SIZING_PROFILES               = 72;
    protected const int ID_TABLE_CONSTRAINTS                 = 73;
    protected const int ID_TABLE_PRIVILEGES                  = 74;
    protected const int ID_TABLES                            = 75;
    protected const int ID_TRANSLATIONS                      = 76;
    protected const int ID_TRIGGER_COLUMN_USAGE              = 77;
    protected const int ID_TRIGGER_ROUTINE_USAGE             = 78;
    protected const int ID_TRIGGER_SEQUENCE_USAGE            = 79;
    protected const int ID_TRIGGER_TABLE_USAGE               = 80;
    protected const int ID_TRIGGERED_UPDATE_COLUMNS          = 81;
    protected const int ID_TRIGGERS                          = 82;
    protected const int ID_TYPE_JAR_USAGE                    = 83;
    protected const int ID_UDT_PRIVILEGES                    = 84;
    protected const int ID_USAGE_PRIVILEGES                  = 85;
    protected const int ID_USER_DEFINED_TYPES                = 86;
    protected const int ID_VIEW_COLUMN_USAGE                 = 87;
    protected const int ID_VIEW_ROUTINE_USAGE                = 88;
    protected const int ID_VIEW_TABLE_USAGE                  = 89;
    protected const int ID_VIEWS                             = 90;
    protected const int ID_SYSTEM_CATALOGS                   = 91;

    /** system table names strictly in order of their ids */
    protected static String[] sysTableNames = {
        "SYSTEM_BESTROWIDENTIFIER",                              //
        "SYSTEM_COLUMNS",                                        //
        "SYSTEM_CROSSREFERENCE",                                 //
        "SYSTEM_INDEXINFO",                                      //
        "SYSTEM_PRIMARYKEYS",                                    //
        "SYSTEM_PROCEDURECOLUMNS",                               //
        "SYSTEM_PROCEDURES",                                     //
        "SYSTEM_SCHEMAS",                                        //
        "SYSTEM_TABLES",                                         //
        "SYSTEM_TABLETYPES",                                     //
        "SYSTEM_TYPEINFO",                                       //
        "SYSTEM_UDTS",                                           //
        "SYSTEM_USERS",                                          //
        "SYSTEM_VERSIONCOLUMNS",                                 //
        "SYSTEM_SEQUENCES",                                      //

        // HSQLDB-specific
        "SYSTEM_CACHEINFO",                                      //
        "SYSTEM_CONNECTION_PROPERTIES",                          //
        "SYSTEM_PROPERTIES",                                     //
        "SYSTEM_SESSIONINFO",                                    //
        "SYSTEM_SESSIONS",                                       //
        "SYSTEM_TEXTTABLES",                                     //

        // SQL 200n
        "ADMINISTRABLE_ROLE_AUTHORIZATIONS",                     //
        "APPLICABLE_ROLES",                                      //
        "ASSERTIONS",                                            //
        "AUTHORIZATIONS",                                        //
        "CHARACTER_SETS",                                        //
        "CHECK_CONSTRAINT_ROUTINE_USAGE",                        //
        "CHECK_CONSTRAINTS",                                     //
        "COLLATIONS",                                            //
        "COLUMN_COLUMN_USAGE",                                   //
        "COLUMN_DOMAIN_USAGE",                                   //
        "COLUMN_PRIVILEGES",                                     //
        "COLUMN_UDT_USAGE",                                      //
        "COLUMNS",                                               //
        "CONSTRAINT_COLUMN_USAGE",                               //
        "CONSTRAINT_TABLE_USAGE",                                //
        "DATA_TYPE_PRIVILEGES",                                  //
        "DOMAIN_CONSTRAINTS",                                    //
        "DOMAINS",                                               //
        "ENABLED_ROLES",                                         //
        "INFORMATION_SCHEMA_CATALOG_NAME",                       //
        "ASSEMBLY_ASSEMBLY_USAGE",                               //
        "ASSEMBLIES",                                            //
        "KEY_COLUMN_USAGE",                                      //
        "METHOD_SPECIFICATIONS",                                 //
        "MODULE_COLUMN_USAGE",                                   //
        "MODULE_PRIVILEGES",                                     //
        "MODULE_TABLE_USAGE",                                    //
        "MODULES",                                               //
        "PARAMETERS",                                            //
        "REFERENTIAL_CONSTRAINTS",                               //
        "ROLE_AUTHORIZATION_DESCRIPTORS",                        //
        "ROLE_COLUMN_GRANTS",                                    //
        "ROLE_MODULE_GRANTS",                                    //
        "ROLE_ROUTINE_GRANTS",                                   //
        "ROLE_TABLE_GRANTS",                                     //
        "ROLE_UDT_GRANTS",                                       //
        "ROLE_USAGE_GRANTS",                                     //
        "ROUTINE_COLUMN_USAGE",                                  //
        "ROUTINE_ASSEMBLY_USAGE",                                //
        "ROUTINE_PRIVILEGES",                                    //
        "ROUTINE_ROUTINE_USAGE",                                 //
        "ROUTINE_SEQUENCE_USAGE",                                //
        "ROUTINE_TABLE_USAGE",                                   //
        "ROUTINES",                                              //
        "SCHEMATA",                                              //
        "SEQUENCES",                                             //
        "SQL_FEATURES",                                          //
        "SQL_IMPLEMENTATION_INFO",                               //
        "SQL_PACKAGES",                                          //
        "SQL_PARTS",                                             //
        "SQL_SIZING",                                            //
        "SQL_SIZING_PROFILES",                                   //
        "TABLE_CONSTRAINTS",                                     //
        "TABLE_PRIVILEGES",                                      //
        "TABLES",                                                //
        "TRANSLATIONS",                                          //
        "TRIGGER_COLUMN_USAGE",                                  //
        "TRIGGER_ROUTINE_USAGE",                                 //
        "TRIGGER_SEQUENCE_USAGE",                                //
        "TRIGGER_TABLE_USAGE",                                   //
        "TRIGGERED_UPDATE_COLUMNS",                              //
        "TRIGGERS",                                              //
        "TYPE_JAR_USAGE",                                        //
        "UDT_PRIVILEGES",                                        //
        "USAGE_PRIVILEGES",                                      //
        "USER_DEFINED_TYPES",                                    //
        "VIEW_COLUMN_USAGE",                                     //
        "VIEW_ROUTINE_USAGE",                                    //
        "VIEW_TABLE_USAGE",                                      //
        "VIEWS",                                                 //
        "SYSTEM_CATALOGS",                                       //
    };

    /** Map: table name => table id */
    protected static IntValueHashMap sysTableNamesMap;

    static DatabaseInformation(){
        sysTableNamesMap = new IntValueHashMap(91);

        for (int i = 0; i < sysTableNames.Length; i++) {
            sysTableNamesMap.put(sysTableNames[i], i);
        }
    }

    protected static int getSysTableID(String token) {
        return sysTableNamesMap.get(token, -1);
    }

    /** Database for which to produce tables */
    protected Database database;

    /**
     * Simple object-wide flag indicating that all of this object's cached
     * data is dirty.
     */
    protected bool isDirty = true;

    /**
     * state flag -- if true, contentful tables are to be produced, else
     * empty (surrogate) tables are to be produced.  This allows faster
     * database startup where user views reference system tables and faster
     * system table structural reflection for table metadata.
     */
    protected bool withContent = false;

    /**
     * Factory method returns the fullest system table producer
     * implementation available.  This instantiates implementations beginning
     * with the most complete, finally choosing an empty table producer
     * implemenation (this class) if no better instance can be constructed.
     * @param db The Database object for which to produce system tables
     * @return the fullest system table producer
     *      implementation available
     */
    public static DatabaseInformation newDatabaseInformation(
            Database db) {

        Type c = null;

        try {
            c = Type.GetType("EffiProz.Core.DbInfos.DatabaseInformationFull");
        } catch (Exception) {
            try {
                c = Type.GetType("EffiProz.Core.DbInfos.DatabaseInformationMain");
            } catch (Exception) {
                c = typeof( DatabaseInformation);
            }
        }

        try {
            Type[]     ctorParmTypes = new Type[]{ typeof(Database) };
            Object[]    ctorParms     = new Object[]{ db };
            ConstructorInfo ctor = c.GetConstructor(ctorParmTypes);

            return (DatabaseInformation) ctor.Invoke(ctorParms);
        } catch (Exception e) {
            System.Diagnostics.Debug.WriteLine( e.StackTrace);
        }

        return new DatabaseInformation(db);
    }

    /**
     * Constructs a new DatabaseInformation instance which knows the names of
     * all system tables (isSystemTable()) but simpy returns null for all
     * getSystemTable() requests. <p>
     *
     * @param db The Database object for which to produce system tables
     */
   public  DatabaseInformation(Database db) {
        database = db;
    }

    /**
     * Tests if the specified name is that of a system table. <p>
     *
     * @param name the name to test
     * @return true if the specified name is that of a system table
     */
    public bool isSystemTable(String name) {
        return sysTableNamesMap.containsKey(name);
    }

    /**
     * Retrieves a table with the specified name whose content may depend on
     * the execution context indicated by the session argument as well as the
     * current value of <code>withContent</code>. <p>
     *
     * @param session the context in which to produce the table
     * @param name the name of the table to produce
     * @return a table corresponding to the name and session arguments, or
     *      <code>null</code> if there is no such table to be produced
     */
    public virtual Table getSystemTable(Session session, String name) {
        return null;
    }

    /**
     * Controls caching of all tables produced by this object. <p>
     *
     * Subclasses are free to ignore this, since they may choose an
     * implementation that does not dynamically generate and/or cache
     * table content on an as-needed basis. <p>
     *
     * If not ignored, this call indicates to this object that all cached
     * table data may be dirty, requiring a complete cache clear at some
     * point.<p>
     *
     * Subclasses are free to delay cache clear until next getSystemTable().
     * However, subclasses may have to be aware of additional methods with
     * semantics similar to getSystemTable() and act accordingly (e.g.
     * clearing earlier than next invocation of getSystemTable()).
     */
    public void setDirty() {
        isDirty = true;
    }

    /**
     * Switches this table producer between producing empty (surrogate)
     * or contentful tables. <p>
     *
     * @param withContent if true, then produce contentful tables, else
     *        produce emtpy (surrogate) tables
     */
    public void setWithContent(bool withContent) {
        this.withContent = withContent;
    }
   
    }
}
